package com.cory.utils.file;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

/**
 * 图片处理工具类
 * 
 * @author xc
 * @version 2016-10-25
 */
public class ImageUtils {
	
	    /**
     * 图片尺寸
     */
	public static int[] size(String src) throws IOException {
		BufferedImage bufferedImage = ImageIO.read(new File(src));
		int width = bufferedImage.getWidth();
		int height = bufferedImage.getHeight();
		return new int[] { width, height };
	}
	
	    /**
     * 等比缩放，居中剪切
     */
	public static String scale(String src, int w, int h) throws IOException {
		int inserTo = src.lastIndexOf(".");
		String dest = src.substring(0, inserTo) + String.format("_%sx%s", w, h) + src.substring(inserTo, src.length());
		scale(src, dest, w, h);
		return dest;
	}
	
	    /**
     * 等比缩放，居中剪切
     */
	public static void scale(String src, String dest, int w, int h) throws IOException {
		String srcSuffix = src.substring(src.lastIndexOf(".") + 1);
		Iterator<ImageReader> iterator = ImageIO.getImageReadersByFormatName(srcSuffix);
		ImageReader reader = (ImageReader) iterator.next();

		InputStream in = new FileInputStream(src);
		ImageInputStream iis = ImageIO.createImageInputStream(in);
		reader.setInput(iis);

		BufferedImage srcBuffered = readScaleBufferedImage(reader, w, h);
		BufferedImage targetBuffered = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

		Graphics graphics = targetBuffered.getGraphics();
        graphics.drawImage(srcBuffered.getScaledInstance(w, h, Image.SCALE_DEFAULT), 0, 0, null); // 绘制缩小后的图

		graphics.dispose();
		srcBuffered.flush();

		ImageIO.write(targetBuffered, srcSuffix, new File(dest));
		targetBuffered.flush();
	}
	
	    /**
     * 图片剪切
     */
	public static String crop(String src, int w, int h) throws IOException {
		return crop(src, 0, 0, w, h);
	}
	
	    /**
     * 图片剪切
     */
	public static void crop(String src, String dest, int w, int h) throws IOException {
		crop(src, dest, 0, 0, w, h);
	}
	
	    /**
     * 图片剪切
     */
	public static String crop(String src, int x, int y, int w, int h) throws IOException {
		int inserTo = src.lastIndexOf(".");
		String dest = src.substring(0, inserTo) + String.format("_%sx%s", w, h) + src.substring(inserTo, src.length());
		crop(src, dest, x, y, w, h);
		return dest;
	}
	
	    /**
     * 图片剪切
     */
	public static void crop(String src, String dest,int x, int y, int w, int h) throws IOException {
		String srcSuffix = src.substring(src.lastIndexOf(".") + 1);
		Iterator<ImageReader> iterator = ImageIO.getImageReadersByFormatName(srcSuffix);
		ImageReader reader = (ImageReader) iterator.next();

		InputStream in = new FileInputStream(src);
		ImageInputStream iis = ImageIO.createImageInputStream(in);
		reader.setInput(iis);

		BufferedImage srcBuffered = readBufferedImage(reader, x, y, w, h);
		BufferedImage targetBuffered = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

		Graphics graphics = targetBuffered.getGraphics();
        graphics.drawImage(srcBuffered, 0, 0, null); // 绘制剪切后的图

		graphics.dispose();
		srcBuffered.flush();

		ImageIO.write(targetBuffered, srcSuffix, new File(dest));
		targetBuffered.flush();
	}
	
	    /**
     * 图片压缩
     */
	public static String optimize(String src, float quality) throws IOException {
		int inserTo = src.lastIndexOf(".");
		String dest = src.substring(0, inserTo) + String.format("_q%s", quality) + src.substring(inserTo, src.length());
		optimize(src, dest, quality);
		return dest;
	}
	
	    /**
     * 图片压缩
     */
	public static void optimize(String src, String dest, float quality) throws IOException {
		Iterator<ImageWriter> iterator = ImageIO.getImageWritersByFormatName("jpeg");
		ImageWriter writer = (ImageWriter) iterator.next();
		
		ImageOutputStream ios = ImageIO.createImageOutputStream(new File(dest));
		writer.setOutput(ios);
		
		ImageWriteParam param = writer.getDefaultWriteParam();
		param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionQuality(quality);

        BufferedImage srcBuffered = ImageIO.read(new File(src));
        writer.write(null, new IIOImage(srcBuffered, null, null), param);
	}
	
	    /**
     * 格式转换
     */
	public static void convert(String src, String dest) throws IOException {
		String destSuffix = dest.substring(dest.lastIndexOf(".") + 1);
		
		BufferedImage srcBuffered = ImageIO.read(new File(src));
		ImageIO.write(srcBuffered, destSuffix, new File(dest));
	}
	
	    /**
     * 图片圆角
     */
	public static String radius(String src) throws IOException {
		int inserTo = src.lastIndexOf(".");
		String dest = src.substring(0, inserTo) + "_r" + src.substring(inserTo, src.length());
		
		int[] size = size(src);
		radius(src, dest, size[0], size[1]);
		return dest;
	}
	
	    /**
     * 图片圆角
     */
	public static void radius(String src, String dest) throws IOException {
		int[] size = size(src);
		radius(src, dest, size[0], size[1]);
	}
	
	    /**
     * 图片圆角
     */
	public static String radius(String src, int radius) throws IOException {
		int inserTo = src.lastIndexOf(".");
		String dest = src.substring(0, inserTo) + String.format("_r%s", radius) + src.substring(inserTo, src.length());
		radius(src, dest, radius, radius);
		return dest;
	}
	
	    /**
     * 图片圆角
     */
	public static String radius(String src, int radiusW, int radiusY) throws IOException {
		int inserTo = src.lastIndexOf(".");
		String dest = src.substring(0, inserTo) + String.format("_%sr%s", radiusW, radiusY) + src.substring(inserTo, src.length());
		radius(src, dest, radiusW, radiusY);
		return dest;
	}
	
	    /**
     * 图片圆角
     */
	public static void radius(String src, String dest, int radius) throws IOException {
		radius(src, dest, radius, radius);
	}
	
	    /**
     * 图片圆角
     */
	public static void radius(String src, String dest, int radiusW, int radiusY) throws IOException {
		BufferedImage srcBuffered = ImageIO.read(new File(src));
		int w = srcBuffered.getWidth();
        int h = srcBuffered.getHeight();
		
		BufferedImage targetBuffered = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g2 = targetBuffered.createGraphics();

		g2.setComposite(AlphaComposite.Src);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(Color.WHITE);
        g2.fill(new RoundRectangle2D.Float(0, 0, w, h, radiusW, radiusY));

        g2.setComposite(AlphaComposite.SrcAtop);
        g2.drawImage(srcBuffered, 0, 0, null);
        g2.dispose();
        
        ImageIO.write(targetBuffered, "png", new File(dest));
	}
	
	    /**
     * 图片水印
     */
	public static void pressImage(String src, String dest, String water, int x, int y, float alpha) throws IOException {
		String srcSuffix = src.substring(src.lastIndexOf(".") + 1);
		Image srcImage = ImageIO.read(new File(src));
		int srcWidth = srcImage.getWidth(null);
		int srcHeight = srcImage.getHeight(null);
		
		BufferedImage targetBuffered = new BufferedImage(srcWidth, srcHeight, BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = targetBuffered.createGraphics();
		g2.drawImage(srcImage, 0, 0, srcWidth, srcHeight, null);
		
		Image waterImage = ImageIO.read(new File(water));
		int waterWidth = waterImage.getWidth(null);
		int waterHeight = waterImage.getHeight(null);
		int[] location = pressLocation(x, y, srcWidth, srcHeight, waterWidth, waterHeight);
		
		g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
		g2.drawImage(waterImage, location[0], location[1], waterWidth, waterHeight, null);
		g2.dispose();
		
		ImageIO.write(targetBuffered, srcSuffix, new File(dest));
	}
	
	    /**
     * 文字水印
     */
	public static void pressText(String src, String dest, String text, int x, int y, float alpha) throws IOException {
        pressText(src, dest, text, "华文彩云", Font.ITALIC, 20, Color.DARK_GRAY, x, y, alpha);
	}
	
	    /**
     * 文字水印
     */
	public static void pressText(String src, String dest, String text, String fontName, int fontStyle, int fontSize, Color color,
			int x, int y, float alpha) throws IOException {
		String srcSuffix = src.substring(src.lastIndexOf(".") + 1);
		Image srcImage = ImageIO.read(new File(src));
		int srcWidth = srcImage.getWidth(null);
		int srcHeight = srcImage.getHeight(null);
		
		BufferedImage targetBuffered = new BufferedImage(srcWidth, srcHeight, BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = targetBuffered.createGraphics();
		g2.drawImage(srcImage, 0, 0, srcWidth, srcHeight, null);
		
		g2.setFont(new Font(fontName, fontStyle, fontSize));
		FontMetrics fm = g2.getFontMetrics();
		Rectangle2D rc = fm.getStringBounds(text, g2);
		int textWidth = new Double(rc.getWidth()).intValue();
		int textHeight = new Double(rc.getHeight()).intValue();
		int[] location = pressLocation(x, y, srcWidth, srcHeight, textWidth, textHeight);
		
		g2.setColor(color);
		g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); 
		g2.drawString(text, location[0], location[1] + textHeight);
		
		g2.dispose();
		
		ImageIO.write(targetBuffered, srcSuffix, new File(dest));
	}
	
	    /**
     * 水印位置，x和y大于0相对左上角，小于0相对右下角，等于0居中
     */
	private static int[] pressLocation(int x, int y, int srcW, int srcH, int pressW, int pressH) {
		if (x < 0) {
			x = srcW - pressW + x;
		} else if ( x == 0) {
			x = (srcW - pressW) / 2;
		}
		if (y < 0) {
			y = srcH - pressH + y;
		} else if ( y == 0) {
			y = (srcH - pressH) / 2;
		}
		return new int[]{ x, y };
	}
	
	private static BufferedImage readScaleBufferedImage(ImageReader reader, int w, int h) throws IOException {
		int srcWidth = reader.getWidth(0);
		int srcHeight = reader.getHeight(0);

		if (w / h > srcWidth / srcHeight) {
			h = h * srcWidth / w;
			w = srcWidth;
			return readBufferedImage(reader, 0, (srcHeight - h) / 2, w, h);
		} else {
			w = w * srcHeight / h;
			h = srcHeight;
			return readBufferedImage(reader, (srcWidth - w) / 2, 0, w, h);
		}
	}
	
	private static BufferedImage readBufferedImage(ImageReader reader, int x, int y, int w, int h) throws IOException {
		ImageReadParam param = reader.getDefaultReadParam();
		
		Rectangle rect = new Rectangle(x, y, w, h);
		param.setSourceRegion(rect);
		BufferedImage srcBuffered = reader.read(0, param);
		return srcBuffered;
	}
}
